﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MediaRecommender.Model;

namespace MediaRecommender.Controller
{
    public class AssociatedPeopleController
    {
        public T CreateAssociatedPerson<T>(string name) where T : AssociatedPerson
        {
            // Returns the the person which was either retrieved or created
            T person = (T)DeterminePerson<T>(name);

            // Updates vectors based on the returned person
            UpdateVector<T>(person);

            return person;
        }

        private T DeterminePerson<T>(string name) where T : AssociatedPerson
        {
            int tempId;
            T personToBeMade;

            // Returns a person if it already exists in the collection
            AssociatedPerson tempPerson = MediaCollection.Instance.ReturnIfInCollection(name);

            if (tempPerson != null)
            {
                if (tempPerson is T)
                {
                    // If the returned person is not null and the same type, the returned person is simply a reference to this person
                    personToBeMade = (T)tempPerson;
                    return personToBeMade;
                }

                // If it is not the same type, a new person is created, taking on the same iD, and the same name
                // This person will then share the same spot in the AssociatedPeopleVectors
                personToBeMade = (T)Activator.CreateInstance(typeof(T), new object[] { name, tempPerson.ID });

                // Adds the person to the collection if the same person in name and type does not exist
                if (MediaCollection.Instance.ReturnAllPeople().Where(x => personToBeMade.Name == x.Name && x is T).Count() == 0)
                    MediaCollection.Instance.DirectAdd(personToBeMade);

                return personToBeMade;
            }

            // If no person were found in the collection, begin making a new person by determining its Id
            List<int> maxId = MediaCollection.Instance.ReturnAllPeople().Select(x => x.ID).ToList();

            // Creates the highest Id possible, based on those already in the collection
            if (maxId.Count() == 0)
                tempId = -1;
            else
                tempId = maxId.Max();
            tempId++;

            // Cannot create new instances of generic classes with non-parameterless constructors
            // Have to use this mess
            // Creates a new person with the name and the newly created Id
            personToBeMade = (T)Activator.CreateInstance(typeof(T), new object[] { name, tempId });

            return personToBeMade;
        }

        private void UpdateVector<T>(T person) where T: AssociatedPerson
        {
            // If the Id is higher than the total number of people in the collection, it must mean that it is brand new person to the collection
            if (MediaCollection.Instance.ReturnAssociatedPeopleVector().Count >= person.ID)
            {
                // Adds the person to the collection
                MediaCollection.Instance.AddPerson(person);
                return;
            }
        }
    }
}